<template>
	<div class="osd">
		<div class="header">
			<el-form inline>
				<el-form-item label="节点">
					<el-select class="mr10 width-150" v-model="nodeName" placeholder="请选择节点" v-loading="!nodeName" @change="changeNode">
						<el-option v-for="node of nodeList" :key="node.nodeName" :value="node.nodeName" :label="node.nodeName" />
					</el-select>
				</el-form-item>
				<el-form-item label="osd" :error="nodeName&&!osdName?'请选择osd':''">
					<el-select class="width-150" v-model="osdName" placeholder="请选择osd" v-loading="!nodeName" @change="changeOsd">
						<el-option v-for="osd of osdList" :key="osd.osdName" :value="osd.osdName" :label="osd.osdName" />
					</el-select>
				</el-form-item>
			</el-form>
		</div>
		<el-descriptions class="info mt15" title="基本信息" :column="4" size="large" border>
			<el-descriptions-item label="盘符">{{ devicePath }}</el-descriptions-item>
			<el-descriptions-item label="类型">{{ deviceType }}</el-descriptions-item>
			<el-descriptions-item label="deviceId">{{ deviceId }}</el-descriptions-item>
			<el-descriptions-item label="所处节点IP">{{ nodeIp }}</el-descriptions-item>
		</el-descriptions>
		<div class="content" v-if="isChart">
			<h3 class="mt15 w100">{{osdName}}性能</h3>
			<el-card>
				<Line title="OPS" name="ops" :data="state.osdOpsData" :x-interval-show="2" y-unit="次/秒"/>
			</el-card>
			<el-card>
				<Line title="BPS" name="bps" :data="state.osdBpsData" :x-interval-show="2" y-unit="B/s" />
			</el-card>
			<el-card class="w100">
				<Line title="延迟" name="delay" :data="state.delayData" y-unit="ms" />
			</el-card>
			<h3 class="mt15 w100">{{osdName}}对应物理磁盘性能</h3>
			<el-card>
				<Line title="IOPS" name="diskIops" :data="state.diskIopsData" :x-interval-show="2" y-unit="次/秒"/>
			</el-card>
			<el-card>
				<Line title="BPS" name="diskBps" :data="state.diskBpsData" :x-interval-show="2" y-unit="kBs" />
			</el-card>
			<el-card class="w100">
				<Line title="瞬时占用率" name="employ" :data="state.employData" y-unit="%" />
			</el-card>
		</div>
	</div>
</template>
<script lang="ts" setup>
import { computed, defineAsyncComponent, inject, onUnmounted, reactive, Ref, ref, watch } from 'vue';
import { useMonitorApi } from '/@/api/monitor-center';
import { LineChartData } from '/@/types';
import { lineTimeHandle, fillDates } from '/@/utils/other';
import { dayjs } from 'element-plus';
import { opsMap, osdDelayMap } from '/@/utils/const';

interface DataState{
	osdOpsData:LineChartData;
	osdBpsData:LineChartData;
	delayData:LineChartData;
	diskIopsData:LineChartData;
	diskBpsData:LineChartData;
	employData:LineChartData;
}

const Line = defineAsyncComponent(() => import('/@/components/echarts/line.vue'));

const monitorApi = useMonitorApi();
const nodeList = inject<Ref<any[]>>('node-list', ref([]));
const nodeName = ref();
const osdList = computed(() => {
	const node = nodeName.value ? nodeList.value.find((item:any) => item.nodeName === nodeName.value) : [];
	const _osdList = node?.devices?.filter((item:any) => item.deviceStatus === 0).map((item:any) => ({ ...item, osdName: 'osd.' + item.osdId }));
	return _osdList || [];
});
const osdName = ref();
const devicePath = computed(() => osdList.value.find((item:any) => item.osdName === osdName.value)?.devicePath);
const deviceType = computed(() => osdList.value.find((item:any) => item.osdName === osdName.value)?.deviceType);
const deviceId = computed(() => osdList.value.find((item:any) => item.osdName === osdName.value)?.deviceId);
const nodeIp = computed(() => nodeList.value.find((item:any) => item.nodeName === nodeName.value)?.nodeIp);
const state = reactive<DataState>({
	osdOpsData: {
		seriesNames: [],
		seriesData: []
	},
	osdBpsData: {
		seriesNames: [],
		seriesData: []
	},
	delayData: {
		seriesNames: [],
		seriesData: []
	},
	diskIopsData: {
		seriesNames: [],
		seriesData: []
	},
	diskBpsData: {
		seriesNames: [],
		seriesData: []
	},
	employData: {
		seriesNames: [],
		seriesData: []
	}
});
const isChart = ref(false);
const datetimerange = inject('datetimerange', ref());
const defaultdaterange = inject('defaultdaterange', ref());
// get data
const getOsdMon = () => {
	if (!osdName.value) return;
	const parmas = {
		osdName: osdName.value,
		durationVO: {
			start: datetimerange.value ? datetimerange.value[0] : dayjs().subtract(defaultdaterange.value[0], defaultdaterange.value[1]).format('YYYY-MM-DD HH:mm:ss'),
			end: datetimerange.value ? datetimerange.value[1] : dayjs().format('YYYY-MM-DD HH:mm:ss'),
		}
	};
	monitorApi.getOsdMon(parmas).then((res:any) => {
		const osdOps = fillDates(parmas.durationVO.start, res.data.osd.ops);
		const osdBps = fillDates(parmas.durationVO.start, res.data.osd.bps);
		const osdLatency = fillDates(parmas.durationVO.start, res.data.osd.latency);
		const diskIops = fillDates(parmas.durationVO.start, res.data.device.iops);
		const diskBps = fillDates(parmas.durationVO.start, res.data.device.bps);
		const diskUtilization = fillDates(parmas.durationVO.start, { 占用率: res.data.device.utilization });

		state.osdOpsData = lineTimeHandle(osdOps, opsMap);
		state.osdBpsData = lineTimeHandle(osdBps, opsMap);
		state.delayData = lineTimeHandle(osdLatency, osdDelayMap, (data) => {
			if (typeof (data) !== 'number') return data;
			return parseFloat(data.toFixed(3));
		});
		state.diskIopsData = lineTimeHandle(diskIops, opsMap);
		state.diskBpsData = lineTimeHandle(diskBps, opsMap, (data) => {
			if (typeof (data) !== 'number') return data;
			return parseFloat((data).toFixed(3));
		});
		state.employData = lineTimeHandle(diskUtilization, undefined, (data) => {
			if (typeof (data) !== 'number') return data;
			return parseFloat((data * 100).toFixed(3));
		});
	}).catch(() => {
		state.osdOpsData = lineTimeHandle();
		state.osdBpsData = lineTimeHandle();
		state.delayData = lineTimeHandle();
		state.diskIopsData = lineTimeHandle();
		state.diskBpsData = lineTimeHandle();
		state.employData = lineTimeHandle();
	});
};
// select node
const changeNode = (val:string) => {
	osdName.value = '';
	nodeName.value = val;
	setTimeout(() => {
		isChart.value = false;
	});
};
// select osd
const changeOsd = (val:string) => {
	isChart.value = true;
	osdName.value = val;
};
const activeTab = inject('activeTab', ref('osd'));
const interval = inject('interval', ref(5000));
const timer = ref();
// Start the timer and call the interface immediately
const openTimer = () => {
	if (!timer.value) {
		getOsdMon();
		timer.value = setInterval(getOsdMon, interval.value);
	}
};
// close Timer
const closeTimer = () => {
	if (timer.value) {
		clearInterval(timer.value);
		timer.value = null;
	}
};
const handle = () => {
	if (activeTab.value === 'osd') {
		if (isChart.value) {
			if (nodeName.value && osdName.value) {
				if (datetimerange.value) {
					getOsdMon();
					closeTimer();
				} else {
					openTimer();
				}
			}
		} else {
			closeTimer();
		}
	} else {
		closeTimer();
	}
};
// Listen to isChart
watch(
	isChart,
	() => {
		handle();
	},
	{
		immediate: true
	}
);
// Listen to node list data
watch(
	nodeList,
	val => {
		nodeName.value = val[0]?.nodeName;
	},
	{
		immediate: true
	}
);
// Switch to the current tab and turn on polling
watch(
	activeTab,
	() => {
		handle();
	},
	{
		immediate: true
	}
);
// Monitoring time range change
watch(
	datetimerange,
	() => {
		handle();
	},
);
// Monitoring time interval change
watch(
	interval,
	() => {
		// Reset timer
		if (timer.value) {
			clearInterval(timer.value);
			timer.value = setInterval(getOsdMon, interval.value);
		}
	}
);
onUnmounted(() => {
	closeTimer();
});
</script>
<style lang="scss" scoped>
.osd{
	:deep(.info){
		margin-top: 15px;
		.el-descriptions__label{
			width: 120px;
		}
		.el-descriptions__body{
			box-shadow: var(--el-box-shadow-light);
		}
	}
}
</style>